/*
 *   A task scheduler that implements Monte-Carlo simulation
 *
 *   Copyright (C) 2011 Systasis Computer Systems, Inc.
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *   
 *   $Id: SkedStorage.java 68 2011-08-01 22:22:17Z jchimene@gmail.com $
 */
package com.systasis.sked.client.model;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.logging.Logger;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayInteger;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.storage.client.StorageMap;
import com.google.inject.Singleton;

@Singleton
public class SkedStorage {

    private class ActivityStorage implements ActivityImporter.Storage, ActivityExporter.Storage {

	@Override
	public void addActivityName(String activityName) {
	    activity.setActivityName(activityName);
	}

	@Override
	public void addBest(Double best) {
	    activity.setBest(round(best, 3));
	}

	@Override
	public void addId(Integer id) {
	    activity.setId(id);
	}

	@Override
	public void addLikely(Double likely) {
	    activity.setLikely(round(likely, 3));
	}

	@Override
	public void addPredecessorList(ArrayList<Integer> predecessorList) {
	    final JsArrayInteger r0 = JavaScriptObject.createArray().cast();
	    for (final int i : predecessorList) {
		r0.push(i);
	    }

	    activity.setPredecessorList(r0);
	}

	@Override
	public void addWorst(Double worst) {
	    activity.setWorst(round(worst, 3));
	}

	@Override
	public String provideActivityName() {
	    return activity.getActivityName();
	}

	@Override
	public Double provideBest() {
	    return activity.getBest();
	}

	@Override
	public Integer provideId() {
	    return activity.getId();
	}

	@Override
	public Double provideLikely() {
	    return activity.getLikely();
	}

	@Override
	public ArrayList<Integer> providePredecessorList() {
	    final JsArrayInteger predecessorList = activity.getPredecessorList();
	    final ArrayList<Integer> r0 = new ArrayList<Integer>();
	    final int r1 = predecessorList.length();
	    for (int i = 0; i < r1; i++) {
		r0.add(predecessorList.shift());
	    }

	    return r0;
	}

	@Override
	public Double provideWorst() {
	    return activity.getWorst();
	}

	private Double round(Double value, int places) {
	    return BigDecimal.valueOf(value).setScale(places, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
    }

    static private ActivityJso activity;

    private static Storage getStorage() throws UnsupportedOperationException {
	final Storage storage = Storage.getLocalStorageIfSupported();
	if (null == storage) {
	    throw (new UnsupportedOperationException("Cannot save/load project: local storage not supported"));
	}
	return storage;
    }

    final private ActivityStorage activityStorage;

    private StorageMap storageMap;

    final Logger logger = Logger.getLogger(SkedStorage.class.getName());

    public SkedStorage() {
	activity = JavaScriptObject.createObject().cast();
	activityStorage = new ActivityStorage();
    }

    public ActivityStorage get() {
	return activityStorage;
    }

    public StorageMap getStorageMap() throws Exception {
	try {
	    if (null == storageMap) {
		storageMap = new StorageMap(getStorage());
	    }
	} catch (final Exception e) {
	    throw (e);
	}
	return storageMap;
    }

    public void open(String source) {
	activity = JsonUtils.safeEval(source);
    }

    @Override
    public String toString() {
	return activity.export();
    }

}
